package main

import (
	"errors"
	"fmt"
)

func main() {
	err := Test2()
	fmt.Println(err.Error())
	fmt.Println(Cause(err))
}

func Test1() error {
	return errors.New("test1内部错误")
}

func Test2() error {
	err := Test1()
	if err != nil {
		return wrap(err, "test2错误")
	}
	fmt.Println("Test2执行完毕")
	return nil
}

type errWithMsg struct {
	innerError error
	msg        string
}

func (ewm *errWithMsg) Error() string {
	return ewm.msg + ": " + ewm.innerError.Error()
}

func (ewm *errWithMsg) Cause() error {
	return ewm.innerError
}

func wrap(err error, msg string) error {
	return &errWithMsg{innerError: err, msg: msg}
}

func Cause(err error) error {
	type causer interface {
		Cause() error
	}
	for err != nil {
		causer, ok := err.(causer)
		if !ok {
			break
		}
		err = causer.Cause()
	}
	return err
}
